package com.ljb.commlibrary.utils;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Bitmap的工具类
 * Created by ljb on 2017/7/27.
 */

public class BitmapUtils {

    private BitmapUtils() {
    }

    /****************************图片压缩相关*********************************/

    /**
     * 从资源文件加载指定大小的bitmap对象
     *
     * @param res       资源文件对象一般传getResources();
     * @param resId     资源文件id
     * @param reqWidth  要求的宽
     * @param reqHeight 要求的高
     * @return 指定大小的Bitmap对象
     */
    public static Bitmap getBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
        //First decode with inJustDecodeBounds=true to check dimensions
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        //Calculate inSampleSize
        options.inSampleSize = calculateInSamepleSize(options, reqWidth, reqHeight);
        //Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    /**
     * 从本地文件加载指定大小的Bitamp对象
     *
     * @param pathName  图片文件路径
     * @param reqWidth  要求的宽
     * @param reqHeight 要求的高
     * @return 指定大小的Bitmap对象
     */
    public static Bitmap getBitmapFromFile(String pathName, int reqWidth, int reqHeight) {
        //First decode with inJustDecodeBounds=true to check dimensions
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(pathName, options);
        //Calculate inSampleSize
        options.inSampleSize = calculateInSamepleSize(options, reqWidth, reqHeight);
        //Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(pathName, options);
    }

    /**
     * 从指定的FileDescriptor加载指定大小的bitmap对象
     *
     * @param fd        文件描述对象
     * @param reqWidth  要求的宽
     * @param reqHeight 要求的高
     * @return bitmap对象
     */
    public static Bitmap getBitmapFromFileDescriptor(FileDescriptor fd, int reqWidth, int reqHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFileDescriptor(fd, null, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSamepleSize(options, reqWidth, reqHeight);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFileDescriptor(fd, null, options);
    }

    /**
     * 从InputStream加载指定大小的Bitamp对象
     *
     * @param inputStream 输入流
     * @param reqWidth    要求的宽
     * @param reqHeight   要求的高
     * @return bitmap对象
     */
    public static Bitmap getBitmapFromStream(InputStream inputStream, int reqWidth, int reqHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(inputStream, null, options);
        options.inSampleSize = calculateInSamepleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeStream(inputStream, null, options);
    }

    /**
     * 从字节数组中加载地址大小的Bitmap对象
     *
     * @param bytes     字节数组
     * @param reqWidth  目标宽度
     * @param reqHeight 目标高度
     * @return Bitmap对象
     */
    public static Bitmap getBitmapFromBytes(byte[] bytes, int reqWidth, int reqHeight) {
        if (bytes == null || bytes.length == 0)
            return null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
        options.inSampleSize = calculateInSamepleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    }

    /**
     * 压缩图片大小
     *
     * @param bitmap 源bitmap对象
     * @param size   指定压缩后的图片大小,单位是kb
     * @return
     */
    public static Bitmap compressBitmap(Bitmap bitmap, int size) {
        if (size <= 0) {
            size = 10;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int option = 100;
        while (baos.toByteArray().length / 1024 > size) {
            baos.reset();
            bitmap.compress(Bitmap.CompressFormat.JPEG, option, baos);
            option -= 10;
        }
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        return BitmapFactory.decodeStream(bais, null, null);
    }


    /**
     * 对图片进行放大缩小
     *
     * @param bitmap    源bitmap对象
     * @param reqWidth  目标宽
     * @param reqHeight 目标高
     * @return 缩放后的bitmap对象
     */
    public static Bitmap zoom(Bitmap bitmap, int reqWidth, int reqHeight) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidht = ((float) reqWidth / w);
        float scaleHeight = ((float) reqHeight / h);
        matrix.postScale(scaleWidht, scaleHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
    }


    /*******************************Bitmap转换相关***************************************/

    /**
     * 将Bitmap对象转换成字节数组
     *
     * @param bitmap 源Bitmap对象
     * @return 字节数组
     */
    public static byte[] getBytesFromBitmap(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * 从View获取Bitmap对象,使用与任何场景
     *
     * @param view 源View
     * @return bitmap对象
     */
    public static Bitmap getBitmapFromView(View view) {
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.WHITE);
        view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
        view.draw(canvas);
        return bitmap;
    }

    /**
     * 从View获取Bitmap对象,适用于view已经可见的场景
     *
     * @param view 源view
     * @return bitmap对象
     */
    public static Bitmap getBitmapFromView2(View view) {
        view.clearFocus();
        view.setPressed(false);
        // 能画缓存就返回false
        boolean willNotCache = view.willNotCacheDrawing();
        view.setWillNotCacheDrawing(false);
        int color = view.getDrawingCacheBackgroundColor();
        view.setDrawingCacheBackgroundColor(0);
        if (color != 0) {
            view.destroyDrawingCache();
        }
        view.buildDrawingCache();
        Bitmap cacheBitmap = view.getDrawingCache();
        if (cacheBitmap == null) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
        // Restore the view
        view.destroyDrawingCache();
        view.setWillNotCacheDrawing(willNotCache);
        view.setDrawingCacheBackgroundColor(color);
        return bitmap;
    }


    /**
     * 获取圆角图片
     *
     * @param bitmap  源bitmap对象
     * @param roundPx 圆角大小
     * @return 目标bitmap
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

    /**
     * 保存bitmap对象到本地
     *
     * @param bitmap
     * @param saveFile 目标路径
     * @param picName  图片名称
     * @return 保存成功后, 返回保存的路径, 失败返回null
     */
    public static File saveBitmap(Bitmap bitmap, File saveFile, String picName) {
        if (!saveFile.exists()) {
            saveFile.mkdir();
        }
        File file = new File(saveFile, picName);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
            return file;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**************************一条神奇的分割线**************************************/


    //计算采样率
    private static int calculateInSamepleSize(final BitmapFactory.Options options, final int reqWidth, final int reqHeight) {
        //Raw width and height of image
        final int width = options.outWidth;
        final int height = options.outHeight;
        int inSampleSize = 1;
        if (width > reqWidth || height > reqHeight) {
            final int halfWidth = width / 2;
            final int halfHeight = height / 2;
            //height and width larger than the requested height and width
            while (halfWidth / inSampleSize >= reqWidth && halfHeight / inSampleSize >= reqHeight) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
}
